package cn.lyj.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import cn.lyj.dao.BaseDao;


@SuppressWarnings("unchecked")
public abstract class BaseHibernateDaoSupport<T> extends HibernateDaoSupport
		implements BaseDao<T> {
	private Class<T> cls;
	
	public BaseHibernateDaoSupport() {
		cls = (Class<T>) ((ParameterizedType) this.getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public void save(T instance) {
		this.getHibernateTemplate().save(instance);
	}

	public void update(T instance) {
		this.getHibernateTemplate().update(instance);
	}

	public void saveOrUpdate(T instance) {
		this.getHibernateTemplate().saveOrUpdate(instance);
	}

	public T merge(T instance) {
		return this.getHibernateTemplate().merge(instance);
	}

	public void delete(T instance) {
		this.getHibernateTemplate().delete(instance);
	}

	public void delete(Collection<T> instances) {
		this.getHibernateTemplate().deleteAll(instances);
	}

	public Integer delete(final Object[] ids) {
		return this.getHibernateTemplate().execute(new HibernateCallback<Integer>() {
			public Integer doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				String hql = "delete from " + cls.getSimpleName() + " where id in(:ids)"; // 1,2,3,...
				return arg0.createQuery(hql).setParameterList("ids", ids).executeUpdate();
			}
		});
	}

	public T get(Serializable id) {
		return this.getHibernateTemplate().get(cls, id);
	}

	public List<T> findAll() {
		return this.getHibernateTemplate().find("from " + cls.getSimpleName());// from Xxx
	}

	public <E> List<E> findForPage(final String hql, final int pageNo, final int pageSize,
			final Object... values) {
		return this.getHibernateTemplate().execute(new HibernateCallback<List<E>>() {
			
			public List<E> doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query = arg0.createQuery(hql);
				if (values != null && values.length != 0) {
					for (int i = 0; i < values.length; ++i) {
						query.setParameter(i, values[i]);
					}
				}
				// query.setProperties(bean);
				query.setFirstResult((pageNo - 1) * pageSize);
				query.setMaxResults(pageSize);
				return query.list();
			}
		});
	}

	
	// select count(*) + from Xxx where....
	// select ... from A, B where ...
	public Number getTotalCount(String hql, Object... values) {
		if (hql.startsWith("select "))
			hql = "select count(*) " + hql.substring(hql.indexOf(" from ") + 1);
		else
			hql = "select count(*) " + hql;
		return (Number) this.getHibernateTemplate().find(hql, values).get(0);
		// this.getHibernateTemplate().findByValueBean(queryString, valueBean)
	}

	public <E> List<E> find(String hql, Object... values) {
		return this.getHibernateTemplate().find(hql, values);
	}

}
